package com.edu.commons;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.NestedRuntimeException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.ServletException;


/**
 * @ProjectName: summer-project
 * @Titile: GlobalExceptionHandler
 * @Author: Lucky
 * @Description: 全局异常类
 */
//@ControllerAdvice //针对请求页面或者数据的
@RestControllerAdvice //针对请求数据是出现异常的增强
@Slf4j //日志注解
public class GlobalExceptionHandler {
    /**
     * 处理业务异常方法
     * @param e
     * @return
     */
    @ExceptionHandler //异常处理注解，只要出现的异常类型是ServiceException，都会被这个方法进行处理
    public R<Void> ServiceExceptionHandle(ServiceException e){
        return R.fail(e);//返回一个封装的信息
    }

    /**
     * 处理错误请求的异常方法
     * @param e
     * @return
     */
    @ExceptionHandler
    public R<Void> BadRequestHandle(NestedRuntimeException e){
        log.debug("NestedRuntimeException：{}",e.getMessage());
        return R.fail(new ServiceException(ServiceCode.ERROR_BAD_REQUEST, "请求的方式或者数据错误，请检查"));
    }

    /**
     * 处理校验出现异常的方法
     * @param e
     * @return
     */
    @ExceptionHandler
    public R<Void> validateExceptionHandle(BindException e){
        //将获取到的校验注解上的错误信息，进行封装，返回给前端
        return R.fail(new ServiceException(ServiceCode.ERROR_BAD_REQUEST,e.getFieldError().getDefaultMessage()));
    }

    /**
     * 处理servlet出现的异常
     * @param e
     * @return
     */
    @ExceptionHandler
    public R<Void> servletExceptionHandle(ServletException e){
        //异常类型属于没有找到handler的异常
        if(e instanceof NoHandlerFoundException){
            return R.fail(new ServiceException(ServiceCode.ERROR_BAD_REQUEST,"请求的路径有误，请检查"));
        }
        return R.fail(new ServiceException(ServiceCode.ERROR_BAD_REQUEST,e.getMessage()));
    }

    /**
     * 处理未知的异常
     * 如果出现以下的这个异常处理信息，后端一定要及时处理
     * @param e
     * @return
     */
    @ExceptionHandler
    public R<Void> notKnowExceptionHandle(Throwable e){
            //打印异常信息
         e.printStackTrace();//这个方式是堵塞式，不建议使用,项目上线后一定要注释掉
        log.info("未知异常：{}",e.getMessage());
        return R.fail(new ServiceException(ServiceCode.ERROR_UN_KNOW,"系统异常,请联系管理员"));
    }

}
